import { BodySetup } from "utils/creep/CreepSetup";
import { ActionBase, ActionBaseOfCreep } from "../ActionBase";
import { priority } from "utils/constants/definetypes";
import { role_crossLevel } from "utils/constants/moveConstant";
import { PositionHelper } from "utils/position/PositionHelper";
import { UtilsHelper } from "utils/position/UtilsHelper";
import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys";
import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { TeamUtils } from "utils/team/TeamUtils";
import { avoidAnyMove } from "GameLoop/WorldState/mount/move/MoveExtension";

/**
 * 升级Action
 */
export class ActionTeamLineMove  extends ActionBase<IActionCMD<"lineMove">>
{
    public execute(action: IActionCMD<"lineMove">): ActionCode 
    {
        const entity = action.arg.entity;
        const arg = action.arg
      
        const currentpos = entity.getAnchor();
        if(PositionHelper.Distance(currentpos,arg.goal.pos)<arg.goal.range)
        {
            return 0;
        }
         
        //
        // 路径存在且 没有更换目标
        if(!entity.path || !entity.path.goalpos || !PositionHelper.isEqual(arg.goal.pos,entity.path.goalpos) || entity.path.path.length<entity.path.index)
        {
            
            this.initLinePath(entity,currentpos,arg.goal.pos);
            
            
        }
        if(entity.path )
        {
            // global.Log.Info(`State_LineMove assert4`);
            // 接着走路
            // 更新当前的移动指令
            // global.Log.Info(`directive 1`);
             
            if(!entity.path.NextDirections)
            {
                // 没有move，则需要设置
                this.updateNextDirection(entity,entity.path);
            }
            
            // 存在移动指令。调用移动
            if(entity.path.NextDirections)
            {
                 
                // global.Log.Info(`directive 2`);
                const nextLeaderDirection=   entity.path.NextDirections[0];
                const checkpos = UtilsHelper.GetDirectionPos(currentpos,nextLeaderDirection);
                if(entity.isPositionMoveable(checkpos))
                {
                   // 能移动则检测爬
                    const blockCreeps =  TeamUtils.findBlockCreep(checkpos).filter(e=>entity.creeps.findIndex(f=>f.id == e.id) == -1)
                    const memory = entity.getNodeMemory();
                    if(!memory.blockCreeps)
                    {
                        memory.blockCreeps=[];
                    }
                    let flag_findpath=false;
                    for(const e of blockCreeps)
                    {
                        if(e.my)
                        {
                            avoidAnyMove(e);
                        }
                        else 
                        {
                            memory.blockCreeps.push(e.id);
                            flag_findpath=true;
                        }
                    }
                    memory.blockCreeps=[]
                    if(flag_findpath)
                    {
                        entity.log('warn',` leader:${JSON.stringify(currentpos)}->${JSON.stringify(checkpos)} 被其他玩家的爬挡住无法移动重新寻路`);
                        // 这里已经离目的地很近了。可以切换模式
                        // this.initLinePath(entity,currentpos,arg.goal.pos,[checkpos]);
                         this.updateNextDirection(entity,entity.path);
                    }
                }
                else 
                {
                    // 无法移动
                    entity.log('warn',` leader:${JSON.stringify(currentpos)}->${JSON.stringify(checkpos)} 无法移动重新寻路`);
                    this.initLinePath(entity,currentpos,arg.goal.pos,[checkpos]);
                    this.updateNextDirection(entity,entity.path);
                }
                // entity.log('info',`directive 下一个移动位置 leader:${JSON.stringify(currentpos)} ${JSON.stringify(checkpos)}`);
                entity.teamMove();
            }
        }
        else
        {
             
                // 路径用完了
            this.initLinePath(entity,currentpos,arg.goal.pos);
        }
       
        return 0;
    }

    
    private updateNextDirection(entity:ATeamCombat,path:ITeamPath)
    {
        const nextDirectives:(DirectionConstant|0)[]=[];
        for(let i=0;i<entity.creeps.length;i++)
        {
            const direct = parseInt(path.path[(path.index-i)]) as DirectionConstant;
            if(direct)
            {
                nextDirectives.push(direct);
            }
        }
        if(nextDirectives.length>0)
        {
            path.NextDirections = nextDirectives// .reverse();// ,应该要reverse?
        }
    }

    private initLinePath(entity:ATeamCombat,from:ObjectRef,To:ObjectRef,BlockPos:RoomPosition[]=[])
    {
        const blockCreeps:Creep[]=[];
        const creeps = entity.creeps;
        const nodememory = entity.getNodeMemory();
        
        for(const id of nodememory.blockCreeps)
        {
            const obj = Game.getObjectById(id);
            if(obj)
            {
                blockCreeps.push(obj);
            }
        }
        const ingourepos:RoomPosition[] = []
        for(const e of creeps)
        {
            ingourepos.push(e.pos);
        }
        // entity.blockCreeps = _.map(blockCreeps,item=>item.id);
        const p_s = PositionHelper.Create(from);
        const p_e = PositionHelper.Create(To);
        
        let isDestoryStructure = (from.roomName == To.roomName) && Game.rooms[To.roomName] && !Game.rooms[To.roomName].IsFriend();

        const opt  = {BlockPosition:_.map(blockCreeps,item=>item.pos) ,ingourepos:ingourepos,isDestoryStructure:isDestoryStructure}  ;
        opt.BlockPosition.push(...BlockPos);
        
        // StationNetwork.getInstance.PathCache.findPathCache()
        let  path = StationNetwork.getInstance.PathFinder.searchPathCache(p_s,{pos:p_e,range:1},opt,["c_structure","c_creep","c_position","c_ingore"] );
        entity.log("warn", `初始化路径`,JSON.stringify(path))
        if(path.icpt && path.cache.length<4)
        {
            (opt as  IPathFinderOpt).IsIngoreRoute = true;
            (opt as  IPathFinderOpt).route=undefined
            path = StationNetwork.getInstance.PathFinder.searchPathCache(p_s,{pos:p_e,range:1},opt,["c_structure","c_creep","c_position","c_ingore"] );
            nodememory.path={
                path:path.cache,
                index:0,
                startpos:from,
                goalpos:To
            }
            entity.log("warn",'找不到完整路径',`忽视路由重新寻路`,JSON.stringify(path))
        }
        else 
        {
            nodememory.path={
                path:path.cache,
                index:0,
                startpos:from,
                goalpos:To
            }
        }
        

        const directives = this.getLineDirection(creeps);
        const Linepath = directives.join("");
        //Memory.Debug[`指令 :`] = JSON.stringify(Linepath);
       //Memory.Debug[`寻路路径 :${JSON.stringify(p_s)}_${JSON.stringify(p_e)}`] = JSON.stringify(entity.path.path);
       nodememory.path.path = Linepath+  nodememory.path.path;
       nodememory.path.index = creeps.length-1;

    }
    private getLineDirection(creepentitys:Creep[])
    {
        const creeps = creepentitys;
        const directions:DirectionConstant[] = [];
        for(let i=creeps.length-1;i>0;i--)
        {
            const pos1 = creeps[i-1].pos;
            const pos2 = creeps[i].pos;
            if(pos1 && pos2)
            {
                directions.push(pos2.getDirectionTo(pos1))
            }
            else
            {
                throw new Error(` creep ${creeps[i].GUID } 或 ${creeps[i+1].GUID }不存在`)
            }
        }
        return directions;
    }
}